﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;


namespace CommonUtils
{
    /// <summary>
    /// 签名常用方法
    /// </summary>
    public static class HashUtil
    {
        /// <summary>
        /// 实体转Dictionary，只处理单层，空值不转义。
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="cfgItem"></param>
        /// <returns></returns>
        public static IDictionary<string, string> ModelToDic<T1>(T1 cfgItem)
        {
            IDictionary<string, string> sdCfgItem = new Dictionary<string, string>();

            System.Reflection.PropertyInfo[] cfgItemProperties = cfgItem.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            foreach (System.Reflection.PropertyInfo item in cfgItemProperties)
            {
                string name = item.Name;
                object value = item.GetValue(cfgItem, null);
                if (value != null && (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String")) && !string.IsNullOrWhiteSpace(value.ToString()))
                {
                    sdCfgItem.Add(name, value.ToString());
                }
            }

            return sdCfgItem;
        }

        public static IDictionary<string, string> ModelToDic (object cfgItem)
        {
            IDictionary<string, string> sdCfgItem = new Dictionary<string, string>();

            System.Reflection.PropertyInfo[] cfgItemProperties = cfgItem.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            foreach (System.Reflection.PropertyInfo item in cfgItemProperties)
            {
                string name = item.Name;
                object value = item.GetValue(cfgItem, null);
                if (value != null && (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String")) && !string.IsNullOrWhiteSpace(value.ToString()))
                {
                    sdCfgItem.Add(name, value.ToString());
                }
            }

            return sdCfgItem;
        }

        /// <summary>
        /// Dictionary转Json字符串
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        public static string DicToJson(IDictionary<string, string> dic)
        {
            StringBuilder sc = new StringBuilder();
            sc.Append("{");
            foreach (var it in dic)
            {
                sc.AppendFormat("\"{0}\":\"{1}\",", it.Key, it.Value);
            }
            string json = sc.ToString();
            json = json.TrimEnd(','); //去掉最后一个逗号。
            json = json + "}";

            return json;
        }



        /// <summary>
        /// 将集合key以ascii码从小到大排序
        /// </summary>
        /// <param name="sArray"></param>
        /// <returns></returns>
        public static IDictionary<string, string> AsciiDictionary(IDictionary<string, string> sArray)
        {
            IDictionary<string, string> asciiDic = new Dictionary<string, string>();
            string[] arrKeys = sArray.Keys.ToArray();
            Array.Sort(arrKeys, string.CompareOrdinal);
            foreach (var key in arrKeys)
            {
                string value = sArray[key];
                asciiDic.Add(key, value);
            }
            return asciiDic;
        }


        /// <summary>
        /// MD5 HASH后，转16进制字符串。 默认UTF-8.
        /// </summary>
        /// <param name="encypStr"></param>
        /// <returns></returns>
        public static string MD5_16(string encypStr)
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;

            //使用GB2312编码方式把字符串转化为字节数组．
            try
            {
                inputBye = Encoding.GetEncoding("UTF-8").GetBytes(encypStr);
            }
            catch (Exception ex)
            {
                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
                Console.WriteLine(ex);
            }
            outputBye = m5.ComputeHash(inputBye);

            retStr = System.BitConverter.ToString(outputBye);
            retStr = retStr.Replace("-", "");
            return retStr;
        }

        /// <summary>
        /// 拼接 K=V A=B 这种URL
        /// </summary>
        /// <param name="sArray"></param>
        /// <returns></returns>
        public static string BuildQueryString(IDictionary<string, string> sArray)
        {

            //拼接 K=V&A=B&c=1 这种URL

            StringBuilder sc = new StringBuilder();

            foreach (var item in sArray)
            {
                string name = item.Key;
                string value = item.Value;
                if (!string.IsNullOrWhiteSpace(value))
                {
                    sc.AppendFormat("{0}={1}&", name, value);
                }

            }

            string fnlStr = sc.ToString();
            fnlStr = fnlStr.TrimEnd('&');

            return fnlStr;
        }


        public static IDictionary<string, string> MergeDictionary(IDictionary<string, string> first, IDictionary<string, string> second)
        {
            var my3 = new Dictionary<string, string>();

            foreach (var item in first)
            {
                if (!my3.ContainsKey(item.Key))
                    my3.Add(item.Key, item.Value);
            }

            foreach (var item in second)
            {
                if (!my3.ContainsKey(item.Key))
                    my3.Add(item.Key, item.Value);
            }

            return my3;
        }

        /// <summary>
        /// MD5 HASH后，转Base64字符串。 默认UTF-8.
        /// </summary>
        /// <param name="encypStr"></param>
        /// <returns></returns>
        public static string MD5_Base64(string encypStr)
        {
            string retStr;
            MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();

            //创建md5对象
            byte[] inputBye;
            byte[] outputBye;

            //使用GB2312编码方式把字符串转化为字节数组．
            try
            {
                inputBye = Encoding.GetEncoding("UTF-8").GetBytes(encypStr);
            }
            catch (Exception ex)
            {
                inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr);
                Console.WriteLine(ex);
            }
            outputBye = m5.ComputeHash(inputBye);


            retStr = Convert.ToBase64String(outputBye);
            return retStr;
        }

        /// <summary>
        /// SHA256 HASH,16进制，小写。
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string SHA256Hash16(string data)
        {
            byte[] bytValue = System.Text.Encoding.UTF8.GetBytes(data);
            SHA256 sha256 = new SHA256CryptoServiceProvider();
            byte[] retVal = sha256.ComputeHash(bytValue);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }


        /// <summary>
        /// 拼接 K=V A=B 这种URL
        /// </summary>
        /// <param name="sArray"></param>
        /// <returns></returns>
        public static string BuildQueryString(IDictionary<string, string> sArray, HashSet<string> skipField)
        {
            //拼接 K=V&A=B&c=1 这种URL
            StringBuilder sc = new StringBuilder();
            foreach (var item in sArray)
            {
                string name = item.Key;
                if (skipField.Contains(name))
                {
                    continue;
                }
                string value = item.Value;
                if (!string.IsNullOrWhiteSpace(value))
                {
                    sc.AppendFormat("{0}={1}&", name, value);
                }
            }
            string fnlStr = sc.ToString();
            fnlStr = fnlStr.TrimEnd('&');
            return fnlStr;
        }


        /// <summary>
        /// 空字符串“”也拼接
        /// </summary>
        /// <param name="sArray"></param>
        /// <param name="skipField"></param>
        /// <param name="emptyStrBuild">空字符串“”也拼接</param>
        /// <returns></returns>
        public static string BuildQueryString(IDictionary<string, string> sArray, HashSet<string> skipField, bool emptyStrBuild)
        {
            //拼接 K=V&A=B&c=1 这种URL
            StringBuilder sc = new StringBuilder();
            foreach (var item in sArray)
            {
                string name = item.Key;
                if (skipField.Contains(name))
                {
                    continue;
                }
                string value = item.Value;
                if (emptyStrBuild)//空字符串""也拼接
                {
                    if (value != null)
                        sc.AppendFormat("{0}={1}&", name, value);
                }
                else
                {
                    if (!string.IsNullOrWhiteSpace(value))
                    {
                        sc.AppendFormat("{0}={1}&", name, value);
                    }
                }

            }
            string fnlStr = sc.ToString();
            fnlStr = fnlStr.TrimEnd('&');
            return fnlStr;
        }


        public static string HmacSHA256_base64(String message, String secret)
        {
            string aa = "";

            byte[] myKey = Encoding.UTF8.GetBytes(secret);

            byte[] myData = Encoding.UTF8.GetBytes(message);


            HMACSHA256 sha256_HMAC = new HMACSHA256(myKey);
            byte[] hashed = sha256_HMAC.ComputeHash(myData);
            //byte[] 根据实际情况转成字符串
            //对E进行Base64编码获得F，F即为签名内容，算法公式为F=Base64_Encode(E)。
            aa = Convert.ToBase64String(hashed);

            return aa;
        }

    }
}
